package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VisitorsApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VisitorsVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MovementService {
    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @DubboReference
    private VisitorsApi visitorsApi;

    public void publishMovement(Movement movement, MultipartFile imageContent[]) throws IOException {
        //判断文本是否为空
        Long userId = UserHolder.getUserId();
        //判断是否被冻结
        String FreezingValue = redisTemplate.opsForValue().get(Constants.FreezingRange_SAY + userId);
        if (FreezingValue != null) {
            if ("never".equals(FreezingValue)) {
                throw new BusinessException(ErrorResult.FreezingPublishNeverError());
            }
            //获取当前时间毫秒值
            long NowTime = new Date().getTime();
            //获取冻结结束时间
            Long FreezingTime = Long.valueOf(FreezingValue);
            //(unFreezingHour)距离解封时间还有多少小时
            Long unFreezingHour = (FreezingTime - NowTime) / 1000 / 3600;
            throw new BusinessException(ErrorResult.FreezingPublishTimeError(unFreezingHour.toString()));
        }
        if(StringUtils.isEmpty(movement.getTextContent())){
            throw new BusinessException(ErrorResult.contentError());
        }
        //如果不为空,获取用户Id
        //Long userId = UserHolder.getUserId();
        //将图片用oos上传到阿里云,获取地址存到集合
        List<String> medias=new ArrayList<>();
        for (MultipartFile multipartFile : imageContent) {
            String upload = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
            medias.add(upload);
        }
        //将数据封装到movement对象
        movement.setUserId(userId);
        movement.setMedias(medias);
        //调用api,传入movement对象
        movementApi.publish(movement);
    }

    public PageResult findByUserId(Long userId, int page, int pagesize) {
        //根据id,调用api,获取pageresult分页对象,里面的movement对象没有用户详情,转化为vo
        PageResult pr=movementApi.findByUserId(userId,page,pagesize);
        //获取分页对象中的动态对象列表
        List<Movement> items = (List<Movement>) pr.getItems();
        //判断列表是否为空
        if(items==null){
            //为空直接返回分页对象
            return pr;
        }
        //获取当前userId的用户信息
        UserInfo userInfo = userInfoApi.findById(userId);
        //不为空循环遍历item列表对象,依次转化为vo对象
        List<MovementsVo> vos=new ArrayList<>();
        for (Movement item : items) {
            //转化为vo对象
            MovementsVo vo = MovementsVo.init(userInfo, item);
            vo.setLoveCount(item.getLoveCount());
            vo.setCommentCount(item.getCommentCount());
            vo.setLikeCount(item.getLikeCount());
            //查询redis中的数据
            String key = Constants.MOVEMENTS_INTERACT_KEY + item.getId();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            String redisValue= (String) redisTemplate.opsForHash().get(key, hashKey);
            //如果存在,给vo赋值
            if (redisValue!=null){
                vo.setHasLiked(1);
            }
            vos.add(vo);
        }
        pr.setItems(vos);
        return pr;
    }

    public PageResult findFriendMovements(int page, int pagesize) {
        //获取当前用户id
        Long userId = UserHolder.getUserId();
        //调用api,查询当前用户的好友动态列表
        List<Movement> list=movementApi.findFriendMovements(page,pagesize,userId);
        return getPageResult(page, pagesize, list);
    }

    private PageResult getPageResult(int page, int pagesize, List<Movement> list) {
        //判断列表是否为空
        if(CollUtil.isEmpty(list)){
            return new PageResult();
        }
        //根据动态列表查询出好友ids列表
        List<Long> ids=CollUtil.getFieldValues(list,"userId",Long.class);
        //根据每一个好友id获取好友个人信息
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids,null);
        //构建一个vo对象,封装成列表
        List<MovementsVo> vos= new ArrayList<>();
        for (Movement movement : list) {
            UserInfo userInfo = map.get(movement.getUserId());
            if(userInfo!=null){
                MovementsVo vo = MovementsVo.init(userInfo, movement);
                //修复点赞状态的bug,判断hashkey是否存在
                String key= Constants.MOVEMENTS_INTERACT_KEY+movement.getId().toHexString();
                String hashKey=Constants.MOVEMENT_LIKE_HASHKEY+UserHolder.getUserId();
                Boolean aBoolean = redisTemplate.opsForHash().hasKey(key, hashKey);
                if(aBoolean){
                    vo.setHasLiked(1);
                }
                String loveKey=Constants.MOVEMENT_LOVE_HASHKEY+UserHolder.getUserId();
                Boolean f = redisTemplate.opsForHash().hasKey(key, loveKey);
                if(f){
                    vo.setHasLoved(1);
                }
                vo.setLikeCount(movement.getLikeCount());
                vo.setLoveCount(movement.getLoveCount());
                vo.setCommentCount(movement.getCommentCount());
                vos.add(vo);
            }
        }
        //构建返回值
        return new PageResult(page, pagesize,0l,vos);
    }

    //查询推荐动态
    public PageResult findRecommendMovements(int page, int pagesize) {
        //获取Redis中的数据
        String redisKey= Constants.MOVEMENTS_RECOMMEND +UserHolder.getUserId();
        String redisValue = redisTemplate.opsForValue().get(redisKey);
        List<Movement> list=new ArrayList<>();
        //判断数据是否为空
        if(StringUtils.isEmpty(redisValue)){
            //如果为空,调用api随机返回10条数据
            list=movementApi.randomMovements(pagesize);
        }else {
            //如果不为空,处理pid数据,以","分割成数组
            String[] values = redisValue.split(",");
            //判断当前页的起始条数是否小于数组长度
            if((page-1)*pagesize<values.length){
                List<Long> pids = Arrays.stream(values).skip((page - 1) * pagesize).limit(pagesize)
                        .map(e -> Long.valueOf(e))
                        .collect(Collectors.toList());
                list=movementApi.findMovementsByPids(pids);
            }

        }
        //调用公共方法创建返回值
        PageResult pr = getPageResult(page, pagesize, list);
        return pr;
    }

    public MovementsVo findById(String id) {
        Movement movement=movementApi.findById(id);
        if(movement!=null){
            UserInfo userInfo = userInfoApi.findById(movement.getUserId());
            MovementsVo vo = MovementsVo.init(userInfo, movement);
            return vo;
        }else {
            return null;
        }
    }
    //首页访客
    public List<VisitorsVo> visitors() {
        //查询访问时间
        String key=Constants.VISITORS_USER;
        String hashKey=String.valueOf(UserHolder.getUserId());
        String value= (String) redisTemplate.opsForHash().get(key,hashKey);
        //判断value是否为null
        Long date=StringUtils.isEmpty(value)?null:Long.valueOf(value);
        //调用api,查询数据列表
        List<Visitors> list=visitorsApi.findByDate(date,UserHolder.getUserId());
        if(CollUtil.isEmpty(list)){
            return new ArrayList<>();
        }
        //提取用户id
        List<Long> visitorUsetIds = CollUtil.getFieldValues(list, "visitorUsetId", Long.class);
        //调用userInfoApi,查询用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(visitorUsetIds, null);
        //循环遍历list,转化为vos
        List<VisitorsVo> vos=new ArrayList<>();
        for (Visitors visitors : list) {
            UserInfo userInfo = map.get(visitors.getVisitorUserId());
            if(userInfo!=null){
                VisitorsVo vo = VisitorsVo.init(userInfo, visitors);
                vos.add(vo);
            }
        }
        //构造返回值
        return vos;
    }
}
